package exemplowebstart;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferStrategy;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.WindowConstants;

public class JogoWebStart extends JFrame implements KeyListener
{
    long PULSOS_DESEJADOS_POR_SEGUNDO = 60;
    double NANOS_ESPERADOS_POR_PULSO = Contador.NANOS_EM_UM_SEGUNDO / PULSOS_DESEJADOS_POR_SEGUNDO;
    BufferStrategy bs;
    ArrayList<Inimigo> inimigos;
    Jogador jogador;
    Point tiro;
    int fase;
    boolean gameOver;
    int limite;
    int pontos;

    public static void main(String[] args)
    {
	JogoWebStart jogo = new JogoWebStart();
	jogo.run();
    }

    public JogoWebStart()
    {
	setTitle("Exemplo WebStart");
	setSize(800, 600);
	setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
	setIgnoreRepaint(true);
	addKeyListener(this);
	inimigos = new ArrayList<Inimigo>();
	limite = getHeight() - 40;
    }

    public void run()
    {
	setVisible(true);
	createBufferStrategy(2);
	bs = getBufferStrategy();
	while (true)
	{
	    pontos = 0;
	    fase = 1;
	    jogador = new Jogador(getWidth() / 2, getHeight() - 10);
	    geraInimigos(fase * 5);
	    tiro = null;
	    long nanoTimeDoProximoPulso = System.nanoTime();
	    gameOver = false;
	    while (!gameOver)
	    {
		Thread.yield();
		while (System.nanoTime() > nanoTimeDoProximoPulso)
		{
		    update();
		    nanoTimeDoProximoPulso += NANOS_ESPERADOS_POR_PULSO;
		}
		render();
	    }
	    render();
	    while (gameOver)
	    {
		Thread.yield();
	    }
	}
    }

    public void update()
    {
	if (tiro != null)
	{
	    tiro.y -= 10;
	    if (tiro.y < 0)
	    {
		tiro = null;
	    }
	}
	boolean achouUmVivo = false;
	for (int i = 0; i < inimigos.size(); i++)
	{
	    Inimigo inimigo = inimigos.get(i);
	    if (inimigo.vivo)
	    {
		if (tiro != null && inimigo.rect.contains(tiro))
		{
		    inimigo.vivo = false;
		    tiro = null;
		    pontos += 10;
		} else
		{
		    achouUmVivo = true;
		    inimigo.rect.x += 5;
		    if (inimigo.rect.x > getWidth())
		    {
			inimigo.rect.x = 5;
			inimigo.rect.y += 30;
			if (inimigo.rect.y > limite)
			{
			    gameOver = true;
			}
		    }
		}
	    }
	}
	if (!achouUmVivo)
	{
	    fase++;
	    geraInimigos(fase * 5);
	}
    }

    public void render()
    {
	Graphics2D g = (Graphics2D) bs.getDrawGraphics();
	g.setColor(Color.black);
	g.fillRect(0, 0, getWidth(), getHeight());
	g.setColor(Color.gray);
	g.drawLine(0, limite, getWidth(), limite);
	g.drawString("PONTOS: " + pontos, 10, getHeight() - 10);
	g.setColor(Color.yellow);
	for (int i = 0; i < inimigos.size(); i++)
	{
	    Inimigo inimigo = inimigos.get(i);
	    if (inimigo.vivo)
	    {
		g.drawOval(inimigo.rect.x, inimigo.rect.y, inimigo.rect.width, inimigo.rect.height);
	    }
	}
	g.setColor(Color.white);
	g.drawLine(jogador.pos.x - 10, jogador.pos.y, jogador.pos.x, jogador.pos.y - 20);
	g.drawLine(jogador.pos.x + 10, jogador.pos.y, jogador.pos.x, jogador.pos.y - 20);
	g.drawLine(jogador.pos.x - 10, jogador.pos.y, jogador.pos.x + 10, jogador.pos.y);
	if (tiro != null)
	{
	    g.setColor(Color.red);
	    g.drawLine(tiro.x, tiro.y - 5, tiro.x, tiro.y + 5);
	}
	if (gameOver)
	{
	    g.setColor(Color.white);
	    g.drawString("FIM DE JOGO!", 400, 200);
	    g.drawString("Pressione ENTER para jogar novamente", 300, 220);
	}
	g.dispose();
	bs.show();
    }

    public void geraInimigos(int qtd)
    {
	inimigos.clear();
	int x = 30;
	int y = 30;
	for (int i = 0; i < qtd; i++)
	{
	    inimigos.add(new Inimigo(x, y));
	    x += 50;
	    if (x > getWidth())
	    {
		x = 30;
		y += 30;
	    }
	}
    }

    public void keyPressed(KeyEvent e)
    {
	int kc = e.getKeyCode();
	if (kc == KeyEvent.VK_LEFT)
	{
	    jogador.pos.x -= 15;
	}
	if (kc == KeyEvent.VK_RIGHT)
	{
	    jogador.pos.x += 15;
	}
	if (kc == KeyEvent.VK_SPACE && tiro == null)
	{
	    tiro = new Point(jogador.pos.x, jogador.pos.y - 25);
	}
        if (kc == KeyEvent.VK_ENTER && gameOver)
	{
	    gameOver = false;
	}
    }

    public void keyReleased(KeyEvent e)
    {
    }

    public void keyTyped(KeyEvent e)
    {
    }
}

class Inimigo
{
    Rectangle rect;
    boolean vivo;

    public Inimigo(int x, int y)
    {
	this.rect = new Rectangle(x, y, 30, 10);
	this.vivo = true;
    }
}

class Jogador
{
    Point pos;

    public Jogador(int x, int y)
    {
	this.pos = new Point(x, y);
    }
}